package cn.iune.backcenter.author.sysinfo;

import java.sql.SQLException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.justep.baas.Utils;
import com.justep.baas.data.Row;
import com.justep.baas.data.RowState;
import com.justep.baas.data.Table;
import com.justep.baas.data.Transform;

@Transactional
@Service
public class SysActionServiceImpl implements ISysActionService {
	
	private Logger log = LogManager.getLogger(this.getClass());

	@Autowired
	private ISysActionDao dao;
	
	/* (non-Javadoc)
	 * @see com.iune.platform.backstage.ISysActionService#getByID(java.lang.String)
	 */
	@Override
	public SysAction getByID(String fID) {
		return dao.getByID(fID);
	}

	/* (non-Javadoc)
	 * @see com.iune.platform.backstage.ISysActionService#getAll()
	 */
	@Override
	public List<SysAction> getAll(){
		return dao.getAll();
	}
	
	/* (non-Javadoc)
	 * @see com.iune.platform.backstage.ISysActionService#delete(java.lang.String)
	 */
	@Transactional
	@Override
	public void delete(String fID) {
		dao.delete(fID);
	}

	@Transactional
	@Override
	public JSONObject save(JSONObject object) throws ParseException {
		//Spring的事务管理默认只对出现运行期异常(java.lang.RuntimeException及其子类)进行回滚。 
		//如果一个方法抛出Exception或者Checked异常，Spring事务管理默认不进行回滚。 
		// JSON转换Table
		//System.out.println(object);
		Table table= Transform.jsonToTable(object);
		
		JSONObject data = new JSONObject();
		data.put("concept", table.getTableName());
		JSONArray rows = new JSONArray();
		List<String> idsNew = new ArrayList<String>();
		List<String> idsDel = new ArrayList<String>();
				
		List<Row> list = table.getRows();
		for(Row row : list){
			JSONObject javaObject= Transform.rowToJavaObject(table, row);
			SysAction obj = JSON.toJavaObject(javaObject, SysAction.class);
			if(RowState.NEW.equals(obj.getRowState())){
				dao.insert(obj);
				idsNew.add(obj.getfID());
			}
			if(RowState.DELETE.equals(obj.getRowState())){
				dao.delete(obj.getfID());
				idsDel.add(obj.getfID());
			}
			if(RowState.EDIT.equals(obj.getRowState())){
				SysAction objNew = dao.update(obj);
				//返回+1后的version到前台BizData中进行刷新，使得前台的version与后台的一致。
				///////////////////////////////////////////////////////////////////////
				JSONObject jsonRow = new JSONObject();
				jsonRow.put("id", obj.getfID());
				jsonRow.put("version", objNew.getVersion());
				rows.add(jsonRow);
				//////////////////////////////////////////////////////////////////////
			}
			//测试使用
			/*
			 * 测试结果表明，如果要更新的java对象与数据库中的数据一致，那么merge函数
			 * 被调用之后返回的version和被调用之前的version是相同的，即使merge之后
			 * 使用了flush（）函数也是一样的效果。
			 */
			/*
			if(RowState.NONE.equals(obj.getRowState())){
				SysAction objNew = dao.update(obj);
				//返回+1后的version到前台BizData中进行刷新，使得前台的version与后台的一致。
				///////////////////////////////////////////////////////////////////////
				SysAction objQuery = dao.getByID(obj.getfID());
				log.info("update更新后flush（）之后查询出objQuery.getVersion()-->>"+objQuery.getVersion());
				JSONObject jsonRow = new JSONObject();
				jsonRow.put("id", obj.getfID());
				jsonRow.put("version", objQuery.getVersion());
				rows.add(jsonRow);
				//////////////////////////////////////////////////////////////////////
			}
			*/
		}
		
		data.put("code", 0);
		data.put("idsNew", idsNew);
		data.put("idsDel", idsDel);
		
		return data;
	}



	/*
	public JSONObject query(JSONObject data) throws Throwable {
		
		// 获取参数
		JSONObject columns = data.getJSONObject("columns"); // 列定义
		String orderBy = data.getString("orderBy"); // 排序
		Integer limit = data.getInteger("limit"); // 分页查询的行数
		Integer offset = data.getInteger("offset"); // 分页查询的行偏移
		String search = data.getString("search"); // 检索关键字
		String filter = data.getString("filter"); // 过滤条件
		String id = data.getString("id");
//		log.info("limit-->"+limit);
//		log.info("offset-->"+offset);
//		log.info("filters-->"+filters);
//		log.info("sqlParams-->"+params);
		
		limit-->15
		offset-->0
		filters-->[unitCode LIKE ? OR unitName LIKE ? OR unitType LIKE ?]
		sqlParams-->[%3%, %3%, %3%]
				
		
		String format = "SELECT %s FROM %s %s %s ";
//		String format = "SELECT SysAction FROM SysAction SysAction %s %s ";
		String select = "SysAction";
		String from = "SysAction SysAction";
		String where = "";

		
		// 存放SQL中的参数值
		List<Object> sqlParams = new ArrayList<Object>();
		// 存放SQL中的过滤条件
		List<String> filters = new ArrayList<String>();
		if (Utils.isNotEmptyString(search)) {
			// 增加过滤条件
			filters.add("actionCode LIKE ? OR actionName LIKE ? ");
			// 检索关键字中如果没有%，则前后自动加%
			search = (search.indexOf("%") != -1) ? search : "%" + search + "%";
			// sqlParams的参数个数和顺序必须与过滤条件的?相匹配 
			for (int i = 0; i < 2; i++) {
				sqlParams.add(search);
			}
		}
		//处理过滤条件
		if (Utils.isNotEmptyString(filter)) {
			filters.add(filter);
		}
		//处理id
		if (Utils.isNotEmptyString(id)) {
			filters.add("fID='"+id+"'");
		}
	
		
		if(filters != null && filters.size() > 0){
			if(where.indexOf("WHERE")== -1){
				//不包含WHERE关键字
				where = "WHERE " + DataUtils.arrayJoin(filters.toArray(), "(%s)", " AND ");
			}else{
				//已包含
				where = where + " AND " + DataUtils.arrayJoin(filters.toArray(), "(%s)", " AND ");
			}
		}
		orderBy = "";//"sortNo ASC";
//		String where = (filters != null && filters.size() > 0) ? " WHERE " + CommonService.arrayJoin(filters.toArray(), "(%s)", " AND ") : "";
		orderBy = Utils.isNotEmptyString(orderBy) ? " ORDER BY " + orderBy : "";
		
		String sql = String.format(format, select, from, where, orderBy);
		System.out.println("sql-->"+sql);
		
		
		//获取数据
		List<Object> list = dao.query(sql,columns,sqlParams,offset,limit);
		
		List<Row> rows = listToRows(list);
		
		Table table = Transform.createTableByColumnsDefine(columns);
		table.appendRows(rows);
		
		if (offset != null && offset.equals(0)) {
			String sqlTotal = String.format(format, "COUNT(*)", from, where, orderBy);
			long rowCount = dao.getCount(sqlTotal, sqlParams);
			table.setTotal((int)rowCount);
		}
		
		JSONObject json = Transform.tableToJson(table);
	
		return json;
	}


	public int save(JSONObject object) throws Throwable {
		// TODO Auto-generated method stub
		// JSON转换Table
		Table table = Transform.jsonToTable(object);
		List<SysAction> list = rowsToList(table.getRows());
		for(SysAction obj : list){
			if(RowState.NEW.equals(obj.getRowState())){
				dao.insert(obj);
			}
			if(RowState.EDIT.equals(obj.getRowState())){
				dao.update(obj);
			}
			if(RowState.DELETE.equals(obj.getRowState())){
				dao.delete(obj.getfID());
			}
		}
		return 0;
	}

	public List<Row> listToRows(List<Object> list){
		//添加行集
		List<Row> rows = new ArrayList<Row>();
		//循环行
	    for(Object o : list){
	    	rows.add(objectToRow((SysAction)o));
	    }
	    return rows;
	}

	public List<SysAction> rowsToList(List<Row> rows){
		//添加行集
		List<SysAction> list = new ArrayList<SysAction>();
		//循环行
	    for(Row r : rows){
	    	list.add(rowToObject(r));
	    }
	    return list;
	}

	public Row objectToRow(SysAction obj){
    	
		Map<String, ColumnValue> values = new HashMap<String, ColumnValue>();
		//循环行中每一列
		ColumnValue value = new ColumnValue(obj.getfID());
		values.put("fID", value);
		
		value = new ColumnValue(obj.getSystemFullID());
 		values.put("systemFullID", value);
		
		value = new ColumnValue(obj.getActionCode());
 		values.put("actionCode", value);
		value = new ColumnValue(obj.getActionName());
 		values.put("actionName", value);
		value = new ColumnValue(obj.getActionDescribe());
 		values.put("actionDescribe", value);

		value = new ColumnValue(obj.getVersion());
 		values.put("version", value);
		
		Row row = new Row(values,RowState.NONE);
		return row;
	}
	
	public SysAction rowToObject(Row row){
		SysAction obj = new SysAction();
		obj.setfID(row.getString("fID"));
	    
		obj.setSystemFullID(row.getString("systemFullID"));
		
		obj.setActionCode(row.getString("actionCode"));
		obj.setActionName(row.getString("actionName"));
		obj.setActionDescribe(row.getString("actionDescribe"));

		obj.setVersion(row.getInteger("version"));
		
		obj.setRowState(row.getState());

		return obj;
	}
	*/
	
	//由模板生成
	/* (non-Javadoc)
	 * @see com.iune.platform.backstage.ISysActionService#templateAdd(java.lang.String, java.lang.String)
	 */
	@Transactional
	@Override
	public void templateAdd(String systemFullID,String billKind){
		if(Utils.isEmptyString(systemFullID) || Utils.isEmptyString(billKind)){
			return ;
		}
		//无论是何种模板
		this.insert(Utils.getUUID(), systemFullID, "create", "新增", "新增单据");
		this.insert(Utils.getUUID(), systemFullID, "delete", "删除", "删除单据");
		this.insert(Utils.getUUID(), systemFullID, "save", "修改", "修改单据");
		this.insert(Utils.getUUID(), systemFullID, "query", "查询", "查询单据列表");
		this.insert(Utils.getUUID(), systemFullID, "export", "输出", "打印和导出");
		
		//如果是单据
		if("Bill".equals(billKind)){
			//子表的增加和删除只是在前端处理data，不影响后端，等同于主表的编辑权限save
//			this.insert(CommonService.getUUID(), systemFullID, "addrow", "添加行", "明细表添加行按钮使用");
//			this.insert(CommonService.getUUID(), systemFullID, "delrow", "删除行", "明细表删除行按钮使用");
			this.insert(Utils.getUUID(), systemFullID, "confirm", "提交", "锁定单据，无法修改");
			this.insert(Utils.getUUID(), systemFullID, "active", "撤回提交", "返回到可以修改的状态");
			this.insert(Utils.getUUID(), systemFullID, "agreeIt", "审批", "是的单据立即生效，如入库单批准后，立即执行入库动作。");
			this.insert(Utils.getUUID(), systemFullID, "unAgree", "撤销审批", "撤销单据已经生效状态");
			this.insert(Utils.getUUID(), systemFullID, "close", "关闭", "使得单据在系统中处于失效状态");
			this.insert(Utils.getUUID(), systemFullID, "open", "打开", "使得单据在系统中处于有效状态");
		}
	}

	/* (non-Javadoc)
	 * @see com.iune.platform.backstage.ISysActionService#insert(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
	@Transactional
	@Override
	public SysAction insert(String fID,String systemFullID,String actionCode,String actionName,String actionDescribe){
		SysAction sysAction = new SysAction();
		sysAction.setfID(fID);
		sysAction.setSystemFullID(systemFullID);
		sysAction.setActionCode(actionCode);
		sysAction.setActionName(actionName);
		sysAction.setActionDescribe(actionDescribe);
		sysAction.setVersion(0);
		dao.insert(sysAction);
		return sysAction;
	}
	/* (non-Javadoc)
	 * @see com.iune.platform.backstage.ISysActionService#getBySystemFullID(java.lang.String)
	 */
	@Override
	public List<SysAction> getBySystemFullID(String systemFullID) {
		return dao.getBySystemFullID(systemFullID);
	}
	

	@Override
	public JSONObject newData(JSONObject param) {
		return dao.create(param);
	}
	
	@Override
	public JSONObject deleteData(JSONObject param) {
		//System.out.println("fileFactoryCreate.param-->>"+param.toJSONString());
		JSONArray ids = param.getJSONArray("ids");
		for(int i=0;i<ids.size();i++){
			String id = ids.getString(i);
			//这里可以增加是否可删除的判断
			
			dao.delete(id);
		}

		JSONObject data = new JSONObject();
		data.put("ids", ids);
		
		JSONObject json = new JSONObject();
		json.put("code", 0);
		json.put("msg", "success");
		json.put("data", data);
		
		return json;
	}

	/*
	在@Transaction注解中定义noRollbackFor和RollbackFor指定某种异常是否回滚。 
	@Transactional(noRollbackFor=RuntimeException.class) 
	@Transactional(RollbackFor=Exception.class) 
	*/
	@Transactional
	@Override
	public JSONObject saveData(JSONObject param) {
		//Spring的事务管理默认只对出现运行期异常(java.lang.RuntimeException及其子类)进行回滚。 
		//如果一个方法抛出Exception或者Checked异常，Spring事务管理默认不进行回滚。 
		// JSON转换Table
		//System.out.println(object);
		JSONObject data;
		try {
			data = this.save(param);
					
			JSONObject json = new JSONObject();
			json.put("code", 0);
			json.put("msg", "success");
			json.put("data", data);
			
			return json;
			
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			log.info("开始打印ParseException");
			e.printStackTrace();
			log.info("e.getMessage()-->>"+e.getMessage());
			log.info("完成打印ParseException");
			
			JSONObject json = new JSONObject();
			json.put("code", -1);
			json.put("msg", e.getMessage());
			
			return json;
		} 
	}
	
	/* (non-Javadoc)
	 * @see com.iune.erp.baseinfo.aaa#queryJDBC(com.alibaba.fastjson.JSONObject)
	 */
	@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	@Override
	public JSONObject queryData(JSONObject param){
		//在此层面（ServiceImpl）统一处理异常，此层面直接被controller调用，面对BizData
		
		try {
			JSONObject jsonTable = dao.query(param);
			
			JSONObject json = new JSONObject();
			json.put("code", 0);
			json.put("msg", "success");
			json.put("data", jsonTable);
			
			return json;
		} catch (SQLException e) {
			e.printStackTrace();
			
			JSONObject json = new JSONObject();
			json.put("code", -1);
			json.put("msg", e.getMessage());
			return json;
		}
	}

	@Override
	public JSONObject validData(JSONObject param) {
		// TODO Auto-generated method stub
		return null;
	}
}
